#pragma once

#include "Common.h"
#include <map>

enum RuleType {
  NullType = 0, ///< 'null' value
  IntType,      ///< signed integer value
  UintType,     ///< unsigned integer value
  RealType,     ///< double value
  StringType,   ///< UTF-8 string value
  BooleanType,  ///< bool value
  ArrayType,    ///< array value (ordered list)
  ObjectType,    ///< object value (collection of name/value pairs).
  DeviceType
};

class RuleObject {
 private:
  RuleObject();
  RuleObject(RuleType type, bool required, RuleType element_type);

 public:
  ~RuleObject();
  typedef std::shared_ptr<RuleObject> Ptr;
  typedef std::map<std::string, Ptr> RuleMap;

  static Ptr CreateBasicRule(RuleType type, bool required = true);

  static Ptr CreateBasicArrayRule(RuleType element_type, bool required = true);

  static Ptr CreateObjectRule(bool required = true);

  static Ptr CreateObjectArrayRule(bool required = true);

  void AddBasicRule(std::string name, RuleType type, bool required);

  void AddBasicArrayRule(std::string name, bool required, RuleType element_type);

  Ptr AddObjectRule(std::string name, bool required);

  Ptr AddObjectArrayRule(std::string name, bool required);

  RuleType Type() const {
    return type_;
  }

  RuleType ElementType() const {
    return element_type_;
  }

  bool Required() const {
    return required_;
  }

  const RuleMap& GetRuleMap() const {
    return rule_map_;
  }

 private:
  RuleType type_;
  bool required_;
  RuleType element_type_;

  std::map<std::string, Ptr> rule_map_;
};
